package com.akeil.flash.dataprocessing;

import java.util.List;

import org.apache.log4j.Logger;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;

import com.akeil.flash.model.EDeviceStatusType;
import com.akeil.flash.pojo.Parameter;
import com.yang.serialport.exception.SendDataToSerialPortFailure;
import com.yang.serialport.exception.SerialPortOutputStreamCloseFailure;
import com.yang.serialport.manage.SerialPortManager;
import com.yang.serialport.utils.ByteUtils;
import com.yang.serialport.utils.CRC16;

import flash.Application;

/**
 * 
 * Copyright: Copyright (c) 2018 HIT akeil
 * 
 * @ClassName: Processor.java
 * @Description: 该类的功能描述
 *
 * @version: v1.0.0
 * @author: SNOW-PC
 * @date: 2018年6月18日 下午5:54:04
 *
 *        Modification History: Date Author Version Description
 *        ---------------------------------------------------------* 2018年6月18日
 *        SNOW-PC v1.0.0 修改原因
 */
public class FlashC51Processor extends AProcessor {
	Logger logger = Logger.getLogger(FlashC51Processor.class);
	
	private byte bt1, bt2, bt3, bt4, bt;
	private byte[] byteRxData = new byte[1024];
	private byte[] byteData = new byte[32];
	private int npos = 0;

	private boolean isCheckCRC = true;

	private ICommandTransfer commandTransfer;
	private float pre_volumn = -1f;
	private float currentTemperature;
	
	public FlashC51Processor(boolean isChkCRC, ICommandTransfer commandTransfer) {
		this.isCheckCRC = isChkCRC;
		this.commandTransfer = commandTransfer;
	}

	public void setCommandTransfer(ICommandTransfer commandTransfer) {
		this.commandTransfer = commandTransfer;
	}

	private boolean CheckCRC(int pos) {
		byte out, data;// 用于保存异或结果
		out = 0x00;

		if (pos > 3) {
			for (int i = 3; i < pos; i++) {
				data = byteRxData[i];
				out ^= data;
			}
			if (out == byteRxData[pos]) {
				return true;
			} else {
				return true;
			}

		} else {
			return false;
		}
	}
	
	private boolean CheckCRC16(int pos) {
		byte[] compute_crc16 = {};
		byte[] context = new byte[32];
		
		/*for (int i = 0; i < 14; i++) {
			System.out.printf("%02X ",byteRxData[i]);
		}*/
		int length = pos - 3;
		
		if (pos > 3) {					
			for (int i = 3; i < pos; i++) {
				context[i - 3] = byteRxData[i];
			}
			compute_crc16 = CRC16.generateCRC16(context, length);
			
			/*for (int i = 0; i < 2; i++) {
				System.out.printf("%02X ",compute_crc16[i]);
			}*/
			
			if((compute_crc16[1] == byteRxData[pos]) && (compute_crc16[0] == byteRxData[pos+1])){
				return true;
			}
			else {
				return false; 
			}

		} else {
			return false;
		}
	}

	/**
	 * 0xaa 0x55 len cmd D0 D1 D2 D3 C1 C2 0xcc 0x33 0xc3 0x3c
	 * 0    1    2   3   4  5  6  7  8  9  10   11   12   13
	 */
	@Override
	public void PushData(byte[] data) {
		/*for(int i = 0;i < data.length;i++){
			System.out.printf("%02X ", data[i]);
		}*/
		int len = data.length;
		try{
			if (len > 0) {
				for (int k = 0; k < len; k++) {
					bt1 = bt2;
					bt2 = bt3;
					bt3 = bt4;
					bt4 = bt;
					bt = data[k];
	
					if (bt == IConstantProcessor.SOF_1 
							&& bt4 == IConstantProcessor.SOF_0) {// 0xaa
																							// 0x55
						// 如果当前字符位0xaa,，这是一条新的指令，此字符保存在m_byteRxData的开始位置
						npos = 0;
						byteRxData[npos] = bt4;
						npos++;
						byteRxData[npos] = bt;
					} else if ((bt == IConstantProcessor.EOF_3) 
							&& (bt4 == IConstantProcessor.EOF_2)
							&& (bt3 == IConstantProcessor.EOF_1) 
							&& (bt2 == IConstantProcessor.EOF_0)) {// 如果当前字符位0xcc,0x33,0xc3,0x3c，这是一条的指令的结束符，此字符意味着保存在m_byteRxData中的所有字符表示一条完整的指令
						npos++;
						byteRxData[npos] = bt;// byteRxData 长度是否可以更长，以符合更长的测量仪器的数据格式
						int length = npos + 1 - 4 - 2 - 2 - 1;// 减去结束符号4字节，头符号2字节，CRC两个字节,长度本身所占空间1字节
						if (length == byteRxData[2]) 
						{
							if (CheckCRC16(npos - 5)) 
							{
								/*for (int i = 0; i < 32; i++)// 32
								// 为设定的数据缓冲区的最大长度，可能不合适，实际的指令的长度大于
								// 32
								{
									byteData[i] = byteRxData[i];
								}
								
								ProcessInfo(byteData, npos + 1); // 由分析处理函数ProcessInfo处理*/
								byteData = new byte[256];
								for (int i = 0; i <= npos; i++)// 32
									// 为设定的数据缓冲区的最大长度，可能不合适，实际的指令的长度大于
									// 32
									{
										byteData[i] = byteRxData[i];
									}
								
									//messageArray.addMessage(new DataMessage("",byteData,10));
									
									ProcessInfo(byteData, npos + 1); // 由分析处理函数ProcessInfo处理
																		// m_byteData
							}
						}
	
						// m_byteData
	
					} else {
						npos++;
						byteRxData[npos] = bt;
					}
				}
			}
		}catch (Exception e) {
			System.out.println("PushData" + e.toString());
		}
	}

	private void ProcessInfo(byte[] datas, int len) {
		/* |AA|55|len|cmd|f1|f2|f3|f4|CC|33|C3|3C| */
		byte cmd = datas[3];
		int length = datas[2];
		StringBuilder sb = new StringBuilder();
		byte tcmd = commandTransfer.transferRecv(cmd);// 转换指令
		float fValue = ByteUtils.byteArrayTofloat(datas, 4);
		//判断是否有串口消息
		Application.flashData.refreshCommunication();

		switch (tcmd) {
		/**
		* 第一部分：接受数据或状态
		*/	
		case IConstantProcessor.TMP://样品温度（原始）
			Application.flashData.setTemperature(fValue);
			currentTemperature = fValue;
			System.out.println("样品温度： " + currentTemperature);
			break;
			
		case IConstantProcessor.ATM://大气压强（原始）
			Application.flashData.setAtm(fValue);
			break;
			
		case IConstantProcessor.DestopTemp://底座温度
			Application.flashData.setDesktopTemperature(fValue);
			break;
			
		case IConstantProcessor.CoupleTemp://电偶温度
			Application.flashData.setCoupleTemperature(fValue);
			System.out.println("电偶温度： " + fValue);
			break;
			
		case IConstantProcessor.FLP://闪点温度
			Application.flashData.setFlashpoint(currentTemperature);
			break;
			
		case IConstantProcessor.Delta://闪点温度校正值
			Application.flashData.setFlashpoint(currentTemperature);
			break;
			
			

		case IConstantProcessor.START://开始试验
			Application.flashData.setStatus(EDeviceStatusType.ANASYSIS);
			break;
			
		case IConstantProcessor.STS:// 设备状态
			Application.flashData.setStatus((int)fValue);
			break;
			
		default:

			break;
		}
	}

	@Override
	public void sendCommand(byte cmdCode) {
		try {
			SerialPortManager.sendToPort(Application.serialport, commandTransfer.generateCommand(cmdCode));
		} catch (SendDataToSerialPortFailure e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SerialPortOutputStreamCloseFailure e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void sendCommand(byte cmdCode,int position) {
		try {
			SerialPortManager.sendToPort(Application.serialport, commandTransfer.generateCommand(cmdCode,position));
		} catch (SendDataToSerialPortFailure e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SerialPortOutputStreamCloseFailure e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void sendType(byte cmdCode,Integer type){
		sendPara(cmdCode, type.floatValue());//类别
	}

	@Override
	public void sendParamter(byte cmdCode) {
	}
	
	public void sendParameter(byte[] context){
		try {
			SerialPortManager.sendToPort(Application.serialport,context);
		} catch (SendDataToSerialPortFailure e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SerialPortOutputStreamCloseFailure e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void sendParameters(List<Byte> cms,List<Object> datas){
		byte[] cmds = {(byte)0xaa,(byte)0x55,(byte)0x00};
		
		int index = 0;
		for (byte b : cms) {
			cmds = ByteUtils.addBytes(cmds,new byte[]{b});
			Object obj = datas.get(0);
			if(obj instanceof Integer){
				cmds = ByteUtils.addBytes(cmds, ByteUtils.floatTobyteArray(((Integer)datas.get(index)).floatValue()));
			}
			
			if(obj instanceof Float){
				cmds = ByteUtils.addBytes(cmds, ByteUtils.floatTobyteArray((Float)datas.get(index)));
			}
			
			index++;
		}
		
		cmds[2] = (byte)(cmds.length - 3);
		byte[] end = {(byte)0x00,(byte)0x00,(byte)0xcc,(byte)0x33,(byte)0xc3,(byte)0x3c};
		cmds = ByteUtils.addBytes(cmds, end);
		
		try {
			SerialPortManager.sendToPort(Application.serialport,cmds);
		} catch (SendDataToSerialPortFailure e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SerialPortOutputStreamCloseFailure e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void sendCharArray(byte cmd,byte[] bytes){
		byte[] cmds = {(byte)0xaa,(byte)0x55,(byte)0x00};

		cmds = ByteUtils.addBytes(cmds,new byte[]{cmd});
		cmds = ByteUtils.addBytes(cmds, bytes);
		
		cmds[2] = (byte)(cmds.length - 3);
		byte[] end = {(byte)0x00,(byte)0x00,(byte)0xcc,(byte)0x33,(byte)0xc3,(byte)0x3c};
		cmds = ByteUtils.addBytes(cmds, end);
		
		
		try {
			SerialPortManager.sendToPort(Application.serialport,cmds);
		} catch (SendDataToSerialPortFailure e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SerialPortOutputStreamCloseFailure e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private void sendPara(byte cmdCode,float value){
		try {
			SerialPortManager.sendToPort(Application.serialport,commandTransfer.generateFloatValue(cmdCode, value));
		} catch (SendDataToSerialPortFailure e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SerialPortOutputStreamCloseFailure e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		try {
			Thread.sleep(20);
		} catch (InterruptedException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
	}

	@Override
	public void selectionChanged(SelectionChangedEvent event) {
		// TODO Auto-generated method stub
		if (event.getSelection() != null) {
			this.setParameter((Parameter) ((IStructuredSelection) event.getSelection()).getFirstElement());
		}
	}

	@Override
	public void sendFunctionFitParameter(byte cmdCode) {
		// TODO 自动生成的方法存根
		
	}

	@Override
	public void sendCoefficients(byte cmdCode,double[] coeffs) {
		// TODO 自动生成的方法存根
		
	}

}
